package com.yhh.xiaohongshuauth.service.Impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.yhh.framework.common.exception.BizException;
import com.yhh.framework.common.response.Response;
import com.yhh.framework.common.utils.JsonUtils;
import com.yhh.xiaohongshuauth.constants.RedisKeyConstants;
import com.yhh.xiaohongshuauth.constants.RoleConstants;
import com.yhh.xiaohongshuauth.domain.dataobject.User;
import com.yhh.xiaohongshuauth.domain.dataobject.UserRoleRel;
import com.yhh.xiaohongshuauth.domain.mapper.UserMapper;
import com.yhh.xiaohongshuauth.domain.mapper.UserRoleRelDao;
import com.yhh.xiaohongshuauth.enums.DeletedEnum;
import com.yhh.xiaohongshuauth.enums.LoginTypeEnum;
import com.yhh.xiaohongshuauth.enums.ResponseCodeEnum;
import com.yhh.xiaohongshuauth.enums.StatusEnum;
import com.yhh.xiaohongshuauth.model.vo.user.UserLoginReqVO;
import com.yhh.xiaohongshuauth.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Date 2025-04-30 11:01
 * @ClassName: UserServiceImpl
 * @Description: TODO
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserRoleRelDao userRoleRelDao;
    @Resource
    private TransactionTemplate transactionTemplate;

    /**
     * @Description: 用户登录/注册
     * @Param:
     * @return:
     */
    @Override
    public Response loginAndRegister(UserLoginReqVO userLoginReqVO) {
        //先拿到手机号跟type
        String phone=userLoginReqVO.getPhone();
        Integer type=userLoginReqVO.getType();
        //初始化登录
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);
        Long userId = null;
        //判断登录逻辑
        switch (loginTypeEnum){
            case VERIFICATION_CODE: //验证码登录
                String verificationCode = userLoginReqVO.getCode();
                // 校验入参验证码是否为空
                Preconditions.checkArgument(StringUtils.isNotBlank(verificationCode), "验证码不能为空");
                //构建验证码 redis key
                String key = RedisKeyConstants.buildVerificationCodeKey(phone);
                //存在redis中该用户的登录验证码
                String sentCode=(String) redisTemplate.opsForValue().get(key);
                //判断用户提交的验证码与redis中存储的验证码是否一致
                if(!verificationCode.equals(sentCode)){
                    throw new BizException(ResponseCodeEnum.VERIFICATION_CODE_ERROR);
                }
                //验证码一致，通过手机号查询记录
                User user = userMapper.selectByPhone(phone);
                log.info("==> 用户是否注册, phone: {}, user: {}", phone, JsonUtils.toJsonString(user));

                //判断是否注册
                if(Objects.isNull(user)){
                    //若用户未注册，则系统自动注册
                    userId=RegisterUser(phone);
                }else {
                    //已注册，获取用户id
                    userId = user.getId();
                }
                break;
            case PASSWORD:
                //todo  密码登录
                break;
            default:
                break;
        }

        // SaToken 登录用户, 入参为用户 ID
        StpUtil.login(userId);

        // 获取 Token 令牌
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 返回 Token 令牌
        return Response.success(tokenInfo.tokenValue);
    }

    /**
     * @author Eason
     * @date 2025-04-30 14:36
     * @description: 系统自动注册用户
    */
    public Long RegisterUser(String phone) {
        return transactionTemplate.execute(status -> {
            try {
                //获取小红书id
                Long xiaohongshuId = redisTemplate.opsForValue().increment(RedisKeyConstants.XIAOHONGSHU_ID_GENERATOR_KEY);

                User user = User.builder()
                        .phone(phone)
                        .xiaohongshuId(String.valueOf(xiaohongshuId)) // 自动生成小红书号 ID
                        .nickname("小红薯" + xiaohongshuId) // 自动生成昵称, 如：小红薯10000
                        .status(StatusEnum.ENABLE.getValue()) // 状态为启用
                        .createTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())) // 修复此处
                        .updateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                        .isDeleted(DeletedEnum.NO.getValue()) // 逻辑删除
                        .build();
                userMapper.insert(user);
                Long userId = user.getId();
                if (userId == null) {
                    log.error("==> 用户插入失败，phone: {}", phone);
                    throw new BizException(ResponseCodeEnum.USER_REGISTER_FAILED);
                }

                UserRoleRel userRoleRel = UserRoleRel.builder()
                        .userId(userId)
                        .roleId(RoleConstants.COMMON_USER_ROLE_ID)
                        .createTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                        .updateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()))
                        .isDeleted(DeletedEnum.NO.getValue())
                        .build();

                int result = userRoleRelDao.insert(userRoleRel);
                if (result <= 0) {
                    log.error("==> 用户角色插入失败，userId: {}", userId);
                    throw new BizException(ResponseCodeEnum.USER_ASSIGN_ROLE_FAILED);
                }

                List<Long> roles = Lists.newArrayList();
                roles.add(RoleConstants.COMMON_USER_ROLE_ID);
                String userRolesKey = RedisKeyConstants.buildUserRoleKey(phone);
                redisTemplate.opsForValue().set(userRolesKey, JsonUtils.toJsonString(roles));
                return userId;
            } catch (Exception e) {
                status.setRollbackOnly(); // 标记事务为回滚
                log.error("==> 系统注册用户异常: ", e);
                return null;
            }
        });
    }

}
